package com.project.lx.gettxtfilename.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;

import com.project.lx.gettxtfilename.R;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: X_Meteor
 * @description: 类描述
 * @version: V_1.0.0
 * @date: 2017/5/11 13:43
 * @company:
 * @email: lx802315@163.com
 */
public class MyView extends View {

    //开始范围
    private int mBeginRange = 8;
    //结束范围
    private int mEndRange = 24;
    /**
     * 内部宽度，也就是标尺每条的宽度
     */
    private int mInnerWidth = 1;
    //标尺条目间的间隔
    private int mIndicatePadding = 15;
    //显示的画笔
    private Paint mIndicatePaint;
    //文字画笔
    private Paint mTextPaint;
    //矩形画笔
    private Paint mBarPaint;
    //矩形画笔2
    private Paint mBar2Paint;
    //显示的宽度
    private int mIndicateWidth;

    //标尺条显示的位置：top，bottom
    private int mGravity;
    //显示的大小
    private float mIndicateScale = 0.7f;

    //每条柱状图的宽度
    private int barWidth = 50;
    //设置一共有几条柱状图
    private int totalBarNum = 3;
    //每条柱状图之间的间距
    private int deltaY = 80;

    /**
     * 标尺矩形（刻度条）
     */
    private Rect mIndicateLoc;
    private Rect mBarLoc;

    private List<int[]> list;

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.MyView);
        barWidth = type.getDimensionPixelSize(R.styleable.MyView_barWidth, 50);
        deltaY = type.getDimensionPixelSize(R.styleable.MyView_deltaY, 80);
        initValue();
    }

    public void initValue() {
        //标尺宽度
        mIndicateWidth = 5;
        //标尺的间隙
        mIndicatePadding = 15;
        //标尺条显示的位置，缺省值为显示在底部
        mGravity = Gravity.BOTTOM;

        //设置标尺的画笔，实心画
        mIndicatePaint = new Paint();
        mIndicatePaint.setStyle(Paint.Style.FILL);
        mIndicatePaint.setStrokeWidth(1);
        //设置文字画笔，实心画，并消除锯齿
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setColor(Color.parseColor("#ebebeb"));
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setTextSize(30);
        //内部宽度（标尺结束范围-标尺开始范围）*指示宽度
        mInnerWidth = (mEndRange - mBeginRange) * getIndicateWidth();
        //标尺定位为一个矩形
        mIndicateLoc = new Rect();

        mBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBarPaint.setColor(Color.parseColor("#ebebeb"));
        mBarPaint.setStyle(Paint.Style.FILL);
        mBarLoc = new Rect();

        mBar2Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBar2Paint.setColor(Color.parseColor("#fe8b1b"));
        mBar2Paint.setStyle(Paint.Style.FILL);

        list = new ArrayList<>();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        int width = widthSpecSize;
        int height = heightSpecSize;

        if (height == 0) {
            height = mIndicateLoc.height() + (barWidth + deltaY) * totalBarNum;
        }
        //如果宽和高都为wrap_content的时候，宽度设置为
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
            width = mInnerWidth;
            height = mIndicateLoc.height() + (barWidth + deltaY) * totalBarNum;
        } else if (widthSpecMode == MeasureSpec.AT_MOST) {
            //如果宽度为wrap_content  高度为match_parent或者精确数值的时候
            width = mInnerWidth + mIndicatePadding * 4;
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            //如果宽度为match_parent或者精确数值的时候，高度为wrap_content
            height = mIndicateLoc.height() + (barWidth + deltaY) * totalBarNum;
        }

        if (widthSpecMode == MeasureSpec.EXACTLY) {
            mIndicatePadding = width / (mEndRange - mBeginRange + 3) / 2;
        }

        setMeasuredDimension(width, height);
    }

    /**
     * 最终指示宽度 ：刻度宽度+刻度内边距+刻度内边距
     *
     * @return
     */
    private int getIndicateWidth() {
        return mIndicateWidth + mIndicatePadding + mIndicatePadding;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        /**
         * 当我们对画布进行旋转，缩放，平移等操作的时候其实我们是想对特定的元素进行操作，
         * 比如图片，一个矩形等，但是当你用canvas的方法来进行这些操作的时候，
         * 其实是对整个画布进行了操作，那么之后在画布上的元素都会受到影响，
         * 所以我们在操作之前调用canvas.save()来保存画布当前的状态，
         * 当操作之后取出之前保存过的状态，这样就不会对其他的元素进行影响
         */
        int count = canvas.save();

        //循环绘制标尺条（刻度），根据最大值和最小值来绘制
        for (int value = mBeginRange, position = 0; value <= mEndRange; value++, position++) {
            drawIndicate(canvas, position);
            //如果需要数字，还需要在刻度下绘制数字
            drawText(canvas, position, String.valueOf(value));
        }

        for (int value = mBeginRange, position = 0; value <= mEndRange; value++, position++) {
            for (int i = 1; i <= totalBarNum; i++) {
                drawBar(canvas, position, i);
            }
        }

        for (int value = mBeginRange, position = 0; value <= mEndRange; value++, position++) {
            for (int i = 0; i < list.size(); i++) {
                int[] time = list.get(i);
                drawBar2(canvas, position, time[0], time[1], time[2]);
            }
        }
        //恢复Canvas的状态
        canvas.restoreToCount(count);
    }

    /**
     * 绘制标尺条（刻度），0到100就会显示100个刻度
     *
     * @param canvas   画布
     * @param position
     */
    private void drawIndicate(Canvas canvas, int position) {
        computeIndicateLoc(mIndicateLoc, position);
        int left = mIndicateLoc.left + mIndicatePadding;
        int right = mIndicateLoc.right - mIndicatePadding;
        int top = mIndicateLoc.top;
        int bottom = mIndicateLoc.bottom;

        if (position % 2 != 0) {
            int indicateHeight = bottom - top;
            if (isAlignTop()) {
                bottom = (int) (top + indicateHeight * mIndicateScale);
            } else {
                top = (int) (bottom - indicateHeight * mIndicateScale);
            }
        }

        mIndicatePaint.setColor(Color.parseColor("#ebebeb"));
        canvas.drawRect(left, top, right, bottom, mIndicatePaint);
    }

    private void drawBar(Canvas canvas, int point, int totalBarNum) {
        computeBarLoc(mBarLoc, point);
        int left = mBarLoc.left;
        int right = mBarLoc.right;
        int top = mBarLoc.top + mIndicateLoc.height() + deltaY * totalBarNum;
        int bottom = mBarLoc.bottom + mIndicateLoc.height() + deltaY * totalBarNum;
        if (point == 0) {
            left = mBarLoc.left + mIndicatePadding;
        }
        if (point == mEndRange - mBeginRange) {
            right = mBarLoc.right - mIndicatePadding;
        }
        canvas.drawRect(left, top, right, bottom, mBarPaint);
    }

    private void drawBar2(Canvas canvas, int point, int startTiem, int endTiem, int barNum) {
        computeBarLoc(mBarLoc, point);

        if (startTiem >= mBeginRange && endTiem <= mEndRange) {

            if (point >= startTiem - mBeginRange && mBeginRange + point < endTiem) {

                int left = mBarLoc.left + mIndicatePadding;
                int right = mBarLoc.right + mIndicatePadding;
                int top = mBarLoc.top + mIndicateLoc.height() + deltaY * barNum;
                int bottom = mBarLoc.bottom + mIndicateLoc.height() + deltaY * barNum;
                if (point == 0) {
                    left = mBarLoc.left + mIndicatePadding;
                }
                if (point == mEndRange - mBeginRange) {
                    right = mBarLoc.right - mIndicatePadding;
                }
                canvas.drawRect(left, top, right, bottom, mBar2Paint);
            }


        }

    }

    public void setTime(List<int[]> list) {
        this.list = list;
        invalidate();
    }

    /**
     * 绘制文字，每2个刻度绘制一个文字用于提示
     *
     * @param canvas
     * @param position
     * @param text
     */
    private void drawText(Canvas canvas, int position, String text) {
        if (position % 2 != 0)
            return;
        if (text.length() == 1) {
            text = "0" + text;
        }
        computeIndicateLoc(mIndicateLoc, position);
        int textHeight = computeTextHeight();

        mTextPaint.setColor(Color.parseColor("#787777"));
        mTextPaint.setTextAlign(Paint.Align.CENTER);

        int x = (mIndicateLoc.left + mIndicateLoc.right) / 2;
        int y = mIndicateLoc.bottom + textHeight;

        if (!isAlignTop()) {
            y = mIndicateLoc.top;
            mTextPaint.getTextBounds(text, 0, text.length(), mIndicateLoc);
            y += mIndicateLoc.top / 2;  //增加一些偏移
        }


        canvas.drawText(text, x, y, mTextPaint);
    }


    private void computeBarLoc(Rect outRect, int position) {

        if (outRect == null)
            return;

        int height = getHeight();
        int indicate = getIndicateWidth();

        int left = (indicate * position);
        int right = left + indicate;
        int top = getPaddingTop();//获得当前View的顶内距
        int bottom = barWidth;//视图高度-视图低内距

        //文字偏移量，左边和右边都加上一个偏移量
        int offsets = getStartOffsets();
        left += offsets;
        right += offsets;
        outRect.set(left, top, right, bottom);
    }

    /**
     * 计算指示器的位置：设置左上右下
     * 最终是设置了此矩形（刻度的左上右下）
     *
     * @param outRect  矩形
     * @param position 位置数值（代表第几个刻度）
     */
    private void computeIndicateLoc(Rect outRect, int position) {
        if (outRect == null)
            return;

        int height = 60;
        int indicate = getIndicateWidth();

        int left = (indicate * position);
        int right = left + indicate;
        int top = getPaddingTop();//获得当前View的顶内距
        int bottom = height - getPaddingBottom();//视图高度-视图低内距

        int textHeight = computeTextHeight();
        if (isAlignTop())
            bottom -= textHeight;//如果是刻度显示在顶部，底部要减去文字的高度
        else
            top += textHeight;//如果是刻度显示在底部，顶部要加上文字的高度

        //文字偏移量，左边和右边都加上一个偏移量
        int offsets = getStartOffsets();
        left += offsets;
        right += offsets;
        outRect.set(left, top, right, bottom);
    }

    /**
     * 计算文字高度
     *
     * @return
     */
    private int computeTextHeight() {
        //使用FontMetrics对象，计算文字的坐标。
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        float textHeight = fontMetrics.descent - fontMetrics.ascent;
        return (int) textHeight;
    }

    /**
     * 计算文字宽度
     *
     * @return
     */
    private float computeTextWidth(String text) {
        return mTextPaint.measureText(text);
    }

    /**
     * 开始偏移，如果要包含文字的话才需要偏移。
     *
     * @return
     */
    private int getStartOffsets() {
        String text = String.valueOf(mBeginRange);
        //返回文字的宽度
        int textWidth = (int) mTextPaint.measureText(text, 0, text.length());
        return textWidth / 2;//实际偏移文字宽度的一半，使其居中显示

    }

    private boolean isAlignTop() {
        //&为位运算符，就是32位二进制值得比较
        return (mGravity & Gravity.TOP) == Gravity.TOP;
    }
}
